package com.tabnet.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import com.tabnet.beans.produit.Accessoire;
import com.tabnet.beans.produit.ProduitCMD;
import com.tabnet.dao.DAOAccessoireCMD;
import com.tabnet.dao.DAOException;
import com.tabnet.dao.DAOFactory;
import com.tabnet.dao.DAOUtilitaire;

public class AccessoireCMDDAOImpl implements DAOAccessoireCMD{
	
	private static final String SQL_SELECT  		= "SELECT Ref_ACCCMD, Description_ACMD, PUACMD "
			+ "FROM AccessoireCMD a, CMD_ACC c WHERE a.Ref_ACCCMD = c.ACCC_Ref AND c.PRDC_ID = ?";
	private static final String SQL_LIER_CMD		= "INSERT INTO CMD_ACC VALUES (?, ?)";
	private static final String SQL_DEL_ACC			= "DELETE FROM CMD_ACC WHERE PRDC_ID=? AND ACCC_Ref=?";
	private static final String SQL_DEL				= "DELETE FROM CMD_ACC WHERE PRDC_ID=?";
	
	private static final String SQL_INSERT			= "INSERT INTO AccessoireCMD VALUES (?, ?, ?)";
	private static final String SQL_SELECT_LAST		= "SELECT Ref_ACCCMD FROM AccessoireCMD WHERE Ref_ACCCMD LIKE ? "
			+ "ORDER BY Ref_ACCCMD DESC LIMIT 0 , 1";

	private DAOFactory _DaoFactory;
	
    public AccessoireCMDDAOImpl( DAOFactory pDaoFactory ) {
        this._DaoFactory = pDaoFactory;
    }

    /**
     * <p>Fonction map<br />
     * Simple méthode utilitaire permettant de faire la correspondance (le
     * mapping) entre une ligne issue de la table des accessoires commander (un ResultSet) et
     * un bean Accessoire.</p>
     * @param resultSet : objet ResultSet
     * @throws SQLException
     * @return un objet Accessoire
     * */
    private Accessoire map( ResultSet resultSet ) throws SQLException {
    	Accessoire oAccessoire = new Accessoire();
    	
    	oAccessoire.setRef( resultSet.getString( "Ref_ACCCMD" ) );
    	oAccessoire.setDescription( resultSet.getString( "Description_ACMD" ) );
    	oAccessoire.set_puA(resultSet.getDouble( "PUACMD" ));
    
        return oAccessoire;
    }
    
    /**
     * <p>Fonction getLastRef<br />
     * Retourne la dernière référence d'un accessoire</p>
     * @param pRef : reference d'un accessoire
     * @throws SQLException
     * @return la derniere reference de la base
     * */
    private String getLastRef(String pRef) throws SQLException, DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet resultSet = null;
        
        String strRef = "";

        try {
        	oConnexion = this._DaoFactory.getConnection();
        	
            // récupération des accessoires commandes
        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_SELECT_LAST, false, pRef + "%");
            resultSet = oPreparedStatement.executeQuery();
            
            if ( resultSet.next() )
            	strRef = resultSet.getString("Ref_ACCCMD");
        }
        catch ( SQLException e ) {
            throw new DAOException(e);
        }
        finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, oPreparedStatement, oConnexion );
        }

        return strRef;
    }
    
	@Override
	public Map<String, Accessoire> getAccessoires(int pIdProduitCMD) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet resultSet = null;
        Map<String, Accessoire> mapAccessoires = new HashMap<String, Accessoire>();
        Accessoire oAccessoire;

        try {
        	oConnexion = this._DaoFactory.getConnection();
        	
            // récupération des accessoires commandes
        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_SELECT, false, pIdProduitCMD);
            resultSet = oPreparedStatement.executeQuery();
            while ( resultSet.next() ) {
            	oAccessoire = map( resultSet );
            	mapAccessoires.put(oAccessoire.getRef(), oAccessoire);
            }
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, oPreparedStatement, oConnexion );
        }

        return mapAccessoires;
	}
	
	@Override
	public void addAccessoire(Accessoire pAccessoire) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
        	oConnexion = this._DaoFactory.getConnection();

        	//Récuperation de la dernière reference de l'option
        	String strLastRef = this.getLastRef(pAccessoire.getRef());
        	
        	if(strLastRef != null && strLastRef.length() == 10){
        		//Incrementation de cette derniere reference
        		int num = Integer.parseInt(strLastRef.substring(5)) + 1; 
        		String strNewRef = pAccessoire.getRef();
        		
        		if(num < 10)
        			strNewRef += "00" + num; 
        		else if(num < 100)
        			strNewRef += "0" + num;
        		else
        			strNewRef += num;
        		
				//insertion d'un accessoire commande
				oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_INSERT, true,
						strNewRef, pAccessoire.getDescription(), pAccessoire.get_puA());
		
	            if ( oPreparedStatement.executeUpdate() == 0 )
	                throw new DAOException( "Échec de l'insertion d'un accessoire commandés." );
        	}
        	else
                throw new DAOException( "Échec de la récupération de la dernière référence." );
	                
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
        	DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, oPreparedStatement, oConnexion );
        }
	}

	@SuppressWarnings("resource")
	@Override
	public void addAccessoires(ProduitCMD oProduitCMD) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
        	oConnexion = this._DaoFactory.getConnection();

        	if(!oProduitCMD.getAccessoiresCmd().isEmpty()) {
	    		for(Accessoire oAccessoire : oProduitCMD.getAccessoiresCmd().values()){
	    				    			
	    			//insertion
	    			oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee(oConnexion,
	    					SQL_LIER_CMD, true, oProduitCMD.getId(), this.getLastRef(oAccessoire.getRef()));
	
	                if ( oPreparedStatement.executeUpdate() == 0 )
	                    throw new DAOException( "Échec de la liaison d'un produit commander avec un accessoire." );
	                
	                oPreparedStatement.close();
	    		}
        	}
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
        	DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, oPreparedStatement, oConnexion );
        }
	}

	@Override
	public void delAccessoire(String pRefAccessoire, int pIdProduitCMD) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
        	oConnexion = this._DaoFactory.getConnection();

        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion,
	    					SQL_DEL_ACC, true, pIdProduitCMD, pRefAccessoire);
	
	        oPreparedStatement.executeUpdate();
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
        	DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, oPreparedStatement, oConnexion );
        }
	}

	@Override
	public void delAccessoires(int pIdProduitCMD) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
        	oConnexion = this._DaoFactory.getConnection();

        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion,
	    					SQL_DEL, true, pIdProduitCMD);
	
	        oPreparedStatement.executeUpdate();
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
        	DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, oPreparedStatement, oConnexion );
        }
		
	}

}
